package rl.educational.workbook;



import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter; 
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.ArrayList; 
import java.util.Calendar;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap; 
import java.util.Map; 
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

import org.apache.commons.lang.StringEscapeUtils;

import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFColor;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook; 

import rl.educational.util.Conversioni;
 

public abstract class ExcelWorkbook {


//	private static final String LABEL_NUMERO_ADR = "AdR";
//	private static final String LABEL_AMBITO = "Ambito";
//	private static final String LABEL_CODICE_AMBITO = "Codice ambito";
//	private static final String LABEL_PROTOCOLLO_EQS = "Prot. EQS";
//	private static final String LABEL_DATA_PROTOCOLLO_EQS = "Data Prot. EQS";
//	private static final String LABEL_PROTOCOLLO_ADR = "Prot. ADR";
//	private static final String LABEL_DATA_PROTOCOLLO_ADR = "Data Prot. ADR";
//	private static final String LABEL_COD_FISCALE = "Cod. fiscale";
//	private static final String LABEL_IMPORTO_DILAZIONATO = "Importo Dilazionato";
//	private static final String LABEL_DATA_PRIMA_RATA_PROTOCOLLO = "Data prima rata protocollo";
//	private static final String LABEL_RATE_PROTOCOLLO = "Num. rate protocollo";
//	private static final String LABEL_DATA_PRIMA_RATA_IN_STAMPA = "Data prima rata in stampa";
//	private static final String LABEL_PROGRESIVO_PRIMA_RATA_IN_STAMPA = "Progressivo prima rata in stampa";
//	private static final String LABEL_DATA_ULTIMA_RATA_IN_STAMPA = "Data ultima rata in stampa";
//	private static final String LABEL_PROGRESIVO_ULTIMA_RATA_IN_STAMPA = "Progressivo ultima rata in stampa";
//	private static final String LABEL_IMPORTO_MINIMO_IN_STAMPA = "Importo minimo in stampa";
//	private static final String LABEL_IMPORTO_MASSIMO_IN_STAMPA = "Importo massimo in stampa";
//	private static final String LABEL_NUMERO_RATE_IN_STAMPA = "Numero rate in stampa";
//	private static final String LABEL_FINE_DILAZIONE = "Fine dilazione";
//	private static final String LABEL_CONTEGGIO_DOC = "Conteggio documenti";
//	private static final String LABEL_BOLLETTINI = "Bollettini";
//	private static final String LABEL_TOTALE = "Totale complessivo"; 
	
	
	// Stili.
//	private static final String ARIAL_DIECI_GRASSETTO_CENTRO_BIANCO = "arialDieciGrassettoCentroBianco";
//	private static final String ARIAL_DIECI_GRASSETTO_CENTRO_NERO = "arialDieciGrassettoCentroNero";
//	private static final String ARIAL_DIECI_GRASSETTO_CENTRO_NERO2 = "arialDieciGrassettoCentroNeroSfondoBlu";
//	private static final String ARIAL_DIECI_GRASSETTO_DESTRA_NERO = "arialDieciGrassettoDestraNero";
//	private static final String ARIAL_DIECI_GRASSETTO_SINISTRA_NERO = "arialDieciGrassettoSinistraNero";
//	private static final String ARIAL_DIECI_DESTRA_SF_BLU = "arialDieciDestraSfondoBlu";
//	private static final String ARIAL_DIECI_SINISTRA_SF_BLU = "arialDieciSinistraSfondoBlu";
//	private static final String ARIAL_DIECI_DESTRA_SF_BIANCO = "arialDieciDestraSfondoBianco";
//	private static final String ARIAL_DIECI_SINISTRA_SF_BIANCO = "arialDieciSinistraSfondoBianco";
	
	
	

	File tempFile = null;
	File outputFile = null;
	Workbook workbook = null;
	Map<String, XSSFCellStyle> stili = null;
	ArrayList<XSSFSheet> sheetList = new ArrayList<XSSFSheet>();
	Map<String, File> sheets = new HashMap<String, File>();
	Map<String, Writer> writers = new HashMap<String, Writer>();

	
	
	public Workbook getWorkbook() {
		return workbook;
	}



	public void setWorkbook(Workbook workbook) {
		this.workbook = workbook;
	}



	public Map<String, XSSFCellStyle> getStili() {
		return stili;
	}



	public void setStili(Map<String, XSSFCellStyle> stili) {
		this.stili = stili;
	}



	public Map<String, File> getSheets() {
		return sheets;
	}



	public void setSheets(Map<String, File> sheets) {
		this.sheets = sheets;
	}



	public Map<String, Writer> getWriters() {
		return writers;
	}



	public void setWriters(Map<String, Writer> writers) {
		this.writers = writers;
	}



	public void open( String filePath, String fileName, String... nomiFoglio ) throws Exception{ 
			outputFile = new File(filePath + File.separator + fileName);

			tempFile = new File( outputFile.getAbsolutePath() + "_TEMP");
			
			// CREAZIONE WORKBOOK.
			workbook = new XSSFWorkbook();
			// CREAZIONE STILI.
			stili = this.creazioneStyles(workbook);
			
			// CREAZIONE FOGLI
			for (int i = 0; i < nomiFoglio.length; i++) {
				sheetList.add( (XSSFSheet) workbook.createSheet(nomiFoglio[i] ) )	;
				
			}	
					
			// SALVATAGGIO TEMPLATE.
			FileOutputStream fileOutputStraem = new FileOutputStream( tempFile );
			
			workbook.write(fileOutputStraem);
			fileOutputStraem.close();
			
			// PREPARAZIONE MAPPA SHEET.

			for (int i = 0; i < nomiFoglio.length; i++) {
				Writer writer;
				File sheetTemp = File.createTempFile( nomiFoglio[i], ".xml");
				writer  = new FileWriter(sheetTemp);
				sheets.put(sheetList.get(i).getPackagePart().getPartName().getName().substring(1), sheetTemp );
				
				writers.put(nomiFoglio[i], writer);
				//writer.close();	
			}	 

	}

	

	public void close() throws Exception{ 

			 for (Writer writer : writers.values() ) {
				 writer.close();
			 }
		
			 FileOutputStream fileOutputStream = new FileOutputStream(  outputFile );
			 this.fillFile(new File(tempFile.getAbsolutePath()), sheets, fileOutputStream);
			 fileOutputStream.close(); 
			 
			 if (tempFile!=null) {
				tempFile.delete();
			}
	}
	 
	public void creazioneSheet(Writer writerOut, boolean tabSelected) throws Exception {
		writerOut.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + 
				"<worksheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\">" + 
				"	<dimension ref=\"A1\"/>" + 
				" 	<sheetViews>" + 
				"		<sheetView workbookViewId=\"0\" tabSelected=\"" + 
				tabSelected + 
				"\"> " + 
				"			<pane ySplit=\"1.0\" state=\"frozen\" topLeftCell=\"A2\" activePane=\"bottomLeft\"/>" + 
				"			<selection pane=\"bottomLeft\"/>" + 
				"		</sheetView>" + 
				"	</sheetViews>" + 
				"	<sheetFormatPr defaultRowHeight=\"15.0\"/>");
	}
	
	

	protected void creazioneSheetDettaglio(Writer writerOut) throws Exception { 
		writerOut.write("<cols>" + "	" +
			"	<col min=\"1\" max=\"1\" width=\"45.0\" customWidth=\"true\"/>" + 
			"	<col min=\"2\" max=\"2\" width=\"45.0\" customWidth=\"true\"/>" + 
			"	<col min=\"3\" max=\"3\" width=\"10.0\" customWidth=\"true\"/>" + 
			"  	<col min=\"4\" max=\"4\" width=\"15.0\" customWidth=\"true\"/>" + 
			"	<col min=\"5\" max=\"5\" width=\"15.0\" customWidth=\"true\"/>" + 
			"	<col min=\"6\" max=\"6\" width=\"20.0\" customWidth=\"true\"/>" + 
			"	<col min=\"7\" max=\"7\" width=\"20.0\" customWidth=\"true\"/>" + 
			"	<col min=\"8\" max=\"8\" width=\"25.0\" customWidth=\"true\"/>" + 
			"	<col min=\"9\" max=\"9\" width=\"25.0\" customWidth=\"true\"/>" + 
			"	<col min=\"10\" max=\"10\" width=\"20.0\" customWidth=\"true\"/>" + 
			"	<col min=\"11\" max=\"11\" width=\"20.0\" customWidth=\"true\"/>" + 
			"	<col min=\"12\" max=\"12\" width=\"20.0\" customWidth=\"true\"/>" + 
			"	<col min=\"13\" max=\"13\" width=\"20.0\" customWidth=\"true\"/>" + 
			"	<col min=\"14\" max=\"14\" width=\"20.0\" customWidth=\"true\"/>" + 
			"	<col min=\"15\" max=\"15\" width=\"20.0\" customWidth=\"true\"/>" + 
			"	<col min=\"16\" max=\"16\" width=\"20.0\" customWidth=\"true\"/>" + 
			"	<col min=\"17\" max=\"17\" width=\"20.0\" customWidth=\"true\"/>" + 
			"	<col min=\"18\" max=\"18\" width=\"15.0\" customWidth=\"true\"/>" + 
			"	<col min=\"19\" max=\"19\" width=\"10.0\" customWidth=\"true\"/>" +
			"</cols>");
					
			writerOut.write("<sheetData>\n");
	}


	public void fillSheet() throws Exception {
		Writer primoWriter = writers.values().iterator().next()  ;
		
		int indiceRigaDettaglio = 1; 
		
		// APERTURA SHEET.
		creazioneSheet(primoWriter, true);
		
		creazioneSheetDettaglio( primoWriter ); 
		
		// DETTAGLIO.
		creazioneIntestazioneDettaglio( primoWriter , stili); 

		creazioneRigaDettaglio(primoWriter, stili,
				"", 
				"", 
				1l, 
				null, 
				indiceRigaDettaglio ); 
		
		// CHIUSURA SHHET.
		chiusuraSheet(primoWriter, true); 
	}
	
	
	private void creazioneRigaDettaglio(Writer writerDettaglio, Map<String, XSSFCellStyle> stili, String descrAdr, String descrAmbito, long codAmbito, Object protocollo, int indiceRiga) throws Exception {
//		try {
//			// STILI.
//			short indiceArialDieciDestra = 0;
//			short indiceArialDieciSinistra = 0;
//
//			if ((indiceRiga % 2) == 0) {
//				indiceArialDieciDestra = stili.get(ARIAL_DIECI_DESTRA_SF_BIANCO).getIndex();
//				indiceArialDieciSinistra = stili.get(ARIAL_DIECI_SINISTRA_SF_BIANCO).getIndex();
//			} else {
//				indiceArialDieciDestra = stili.get(ARIAL_DIECI_DESTRA_SF_BLU).getIndex();
//				indiceArialDieciSinistra = stili.get(ARIAL_DIECI_SINISTRA_SF_BLU).getIndex();
//			}
//			this.creazioneRiga(writerDettaglio, indiceRiga);
//			this.creazioneCellaTesto(writerDettaglio, indiceRiga, 0, descrAdr, indiceArialDieciSinistra);
//			this.creazioneCellaTesto(writerDettaglio, indiceRiga, 1, descrAmbito, indiceArialDieciSinistra);
//			this.creazioneCellaNumerica(writerDettaglio, indiceRiga, 2, codAmbito, indiceArialDieciDestra);
//			this.creazioneCellaNumerica(writerDettaglio, indiceRiga, 3, protocollo.getNumeroProtocolloEQS(), indiceArialDieciDestra);
//			this.creazioneCellaTesto(writerDettaglio, indiceRiga, 4, new Conversioni().date_longToLabel(protocollo.getDataProtocolloEQS()), indiceArialDieciDestra);
//			String identificativoProtocolloADR = protocollo.getNumeroProtocolloADR().trim();
//
//			if (identificativoProtocolloADR != null && !"".equals(identificativoProtocolloADR)) { 
//				this.creazioneCellaTesto(writerDettaglio, indiceRiga, 5,"", indiceArialDieciDestra);
//				this.creazioneCellaTesto(writerDettaglio, indiceRiga, 6, new Conversioni().date_longToLabel(protocollo.getDataProtocolloADR()), indiceArialDieciDestra);
//			} else {
//				this.creazioneCellaTesto(writerDettaglio, indiceRiga, 5, new String(), indiceArialDieciDestra);
//				this.creazioneCellaTesto(writerDettaglio, indiceRiga, 6, new String(), indiceArialDieciDestra);
//			}
//			this.creazioneCellaTesto(writerDettaglio, indiceRiga, 7, protocollo.getCodiceFiscale(), indiceArialDieciSinistra);
//			this.creazioneCellaTesto(writerDettaglio, indiceRiga, 8, Conversioni.valuta_longToLabel(protocollo.getImportoDilazionato()), indiceArialDieciDestra);
//			this.creazioneCellaTesto(writerDettaglio, indiceRiga, 9, new Conversioni().date_longToLabel(protocollo.getDataPrimaRataProtocollo()), indiceArialDieciDestra);
//			this.creazioneCellaNumerica(writerDettaglio, indiceRiga, 10, protocollo.getNumeroRateProtocollo(), indiceArialDieciDestra);
//			this.creazioneCellaTesto(writerDettaglio, indiceRiga, 11, new Conversioni().date_longToLabel(protocollo.getDataMinRataInStampa()), indiceArialDieciDestra);
//			this.creazioneCellaNumerica(writerDettaglio, indiceRiga, 12, protocollo.getRataMinInStampa(), indiceArialDieciDestra);
//			this.creazioneCellaTesto(writerDettaglio, indiceRiga, 13, new Conversioni().date_longToLabel(protocollo.getDataMaxRataInStampa()), indiceArialDieciDestra);
//			this.creazioneCellaNumerica(writerDettaglio, indiceRiga, 14, protocollo.getRataMaxInStampa(), indiceArialDieciDestra);
//			this.creazioneCellaTesto(writerDettaglio, indiceRiga, 15, Conversioni.valuta_longToLabel(protocollo.getImportoMinInStampa()), indiceArialDieciDestra);
//			this.creazioneCellaTesto(writerDettaglio, indiceRiga, 16, Conversioni.valuta_longToLabel(protocollo.getImportoMaxInStampa()), indiceArialDieciDestra);
//			int rateInStampa = (protocollo.getRataMaxInStampa() - protocollo.getRataMinInStampa()) + 1;
//
//			this.creazioneCellaNumerica(writerDettaglio, indiceRiga, 17, rateInStampa, indiceArialDieciDestra);
//			String fineDilazione = "NO";
//			if (protocollo.getRataMaxInStampa() == protocollo.getNumeroRateProtocollo()) {
//				fineDilazione = "SI";
//			}
//			this.creazioneCellaTesto(writerDettaglio, indiceRiga, 18, fineDilazione, indiceArialDieciSinistra);
//			this.chiusuraRiga(writerDettaglio);
//		}
//		catch (Exception exception) {
//			// super.getLogger().error("ERRORE: classe: " + this.getClass().getName() + " metodo: creazioneRigaDettaglio()");
//			throw exception;
//		}
	}
	
	
	
	protected void chiusuraSheet(Writer writerOut, boolean gridLine) throws Exception { 
			writerOut.write("</sheetData>");
			writerOut.write("<printOptions gridLines=\"" + gridLine + "\"/>" + "<pageMargins bottom=\"0.75\" footer=\"0.3\" header=\"0.3\" left=\"0.7\" right=\"0.7\" top=\"0.75\"/>");
			writerOut.write("</worksheet>"); 
	}
	
	
	
	private void creazioneIntestazioneDettaglio(Writer writerDettaglio, Map<String, XSSFCellStyle> stili) throws Exception {
//		try {
//			// STILE.
//			short indiceArialDieciGrassettoCentroACapoAUTO = stili.get(ARIAL_DIECI_GRASSETTO_CENTRO_BIANCO).getIndex();
//
//			this.creazioneRiga(writerDettaglio, 0);
//			this.creazioneCellaTesto(writerDettaglio, 0, 0, LABEL_NUMERO_ADR, indiceArialDieciGrassettoCentroACapoAUTO);
//			this.creazioneCellaTesto(writerDettaglio, 0, 1, LABEL_AMBITO, indiceArialDieciGrassettoCentroACapoAUTO);
//			this.creazioneCellaTesto(writerDettaglio, 0, 2, LABEL_CODICE_AMBITO, indiceArialDieciGrassettoCentroACapoAUTO);
//			this.creazioneCellaTesto(writerDettaglio, 0, 3, LABEL_PROTOCOLLO_EQS, indiceArialDieciGrassettoCentroACapoAUTO);
//			this.creazioneCellaTesto(writerDettaglio, 0, 4, LABEL_DATA_PROTOCOLLO_EQS, indiceArialDieciGrassettoCentroACapoAUTO);
//			this.creazioneCellaTesto(writerDettaglio, 0, 5, LABEL_PROTOCOLLO_ADR, indiceArialDieciGrassettoCentroACapoAUTO);
//			this.creazioneCellaTesto(writerDettaglio, 0, 6, LABEL_DATA_PROTOCOLLO_ADR, indiceArialDieciGrassettoCentroACapoAUTO);
//			this.creazioneCellaTesto(writerDettaglio, 0, 7, LABEL_COD_FISCALE, indiceArialDieciGrassettoCentroACapoAUTO);
//			this.creazioneCellaTesto(writerDettaglio, 0, 8, LABEL_IMPORTO_DILAZIONATO, indiceArialDieciGrassettoCentroACapoAUTO);
//			this.creazioneCellaTesto(writerDettaglio, 0, 9, LABEL_DATA_PRIMA_RATA_PROTOCOLLO, indiceArialDieciGrassettoCentroACapoAUTO);
//			this.creazioneCellaTesto(writerDettaglio, 0, 10, LABEL_RATE_PROTOCOLLO, indiceArialDieciGrassettoCentroACapoAUTO);
//			this.creazioneCellaTesto(writerDettaglio, 0, 11, LABEL_DATA_PRIMA_RATA_IN_STAMPA, indiceArialDieciGrassettoCentroACapoAUTO);
//			this.creazioneCellaTesto(writerDettaglio, 0, 12, LABEL_PROGRESIVO_PRIMA_RATA_IN_STAMPA, indiceArialDieciGrassettoCentroACapoAUTO);
//			this.creazioneCellaTesto(writerDettaglio, 0, 13, LABEL_DATA_ULTIMA_RATA_IN_STAMPA, indiceArialDieciGrassettoCentroACapoAUTO);
//			this.creazioneCellaTesto(writerDettaglio, 0, 14, LABEL_PROGRESIVO_ULTIMA_RATA_IN_STAMPA, indiceArialDieciGrassettoCentroACapoAUTO);
//			this.creazioneCellaTesto(writerDettaglio, 0, 15, LABEL_IMPORTO_MINIMO_IN_STAMPA, indiceArialDieciGrassettoCentroACapoAUTO);
//			this.creazioneCellaTesto(writerDettaglio, 0, 16, LABEL_IMPORTO_MASSIMO_IN_STAMPA, indiceArialDieciGrassettoCentroACapoAUTO);
//			this.creazioneCellaTesto(writerDettaglio, 0, 17, LABEL_NUMERO_RATE_IN_STAMPA, indiceArialDieciGrassettoCentroACapoAUTO);
//			this.creazioneCellaTesto(writerDettaglio, 0, 18, LABEL_FINE_DILAZIONE, indiceArialDieciGrassettoCentroACapoAUTO);
//			this.chiusuraRiga(writerDettaglio);
//		}
//		catch (Exception exception) {
//			// super.getLogger().error("ERRORE: classe: " + this.getClass().getName() + " metodo: creazioneIntestazioneDettaglio()");
//			throw exception;
//		}
	}
	
	protected void creazioneCellaData(Writer writerOut, int indiceRiga, int indiceCella, Date value, int indiceStile) throws Exception {
		Calendar c = Calendar.getInstance();
		c.setTime(value);
		
		if ( c.get(Calendar.YEAR) > 3000) {
			creazioneCellaTesto(writerOut, indiceRiga, indiceCella, "", indiceStile);
		} else{ 
			createCell(writerOut, indiceRiga, indiceCella, DateUtil.getExcelDate(value, false), indiceStile);
		} 
	}

	protected void creazioneCellaData(Writer writerOut, int indiceRiga, int indiceCella, long value, int indiceStile) throws Exception {
		 
		if( new Conversioni().getAnno(value) > 3000){ 
			creazioneCellaTesto(writerOut, indiceRiga, indiceCella, "" , indiceStile);
		} else{
			creazioneCellaTesto(writerOut, indiceRiga, indiceCella, new Conversioni().date_longToLabel(value) , indiceStile); 
		}
		
	}
	
	private void createCell(Writer writerOut, int indiceRiga, int indiceCella, double value, int indiceStile) throws Exception { 
			String riferimentoCella = new CellReference(indiceRiga, indiceCella).formatAsString();
			StringBuffer buffer = new StringBuffer();
			buffer.append("<c r=\"");
			buffer.append(riferimentoCella);
			buffer.append("\" t=\"n\"");
			buffer.append(" s=\"");
			buffer.append(indiceStile);
			buffer.append("\">");
			buffer.append("<v>");
			buffer.append(value);
			buffer.append("</v>");
			buffer.append("</c>");
			writerOut.write(buffer.toString()); 
	}
	
	
	
	protected void creazioneCellaTesto(Writer writerOut, int indiceRiga, int indiceCella, double valore, int indiceStile) throws Exception {
		creazioneCellaTesto(writerOut, indiceRiga, indiceCella, String.valueOf(valore), indiceStile);
	}

	protected void creazioneCellaTesto(Writer writerOut, int indiceRiga, int indiceCella, int valore, int indiceStile) throws Exception {
		creazioneCellaTesto(writerOut, indiceRiga, indiceCella, String.valueOf(valore), indiceStile);
	}
	
	protected void creazioneCellaTesto(Writer writerOut, int indiceRiga, int indiceCella, String valore, int indiceStile) throws Exception {
			if (valore == null) {
				valore = "";
			}
			
			//inizio bug2688
			valore = StringEscapeUtils.escapeXml(valore);
			//fine bug2688
			
			String riferimentoCella = new CellReference(indiceRiga, indiceCella).formatAsString();
			writerOut.write("<c r=\"" + riferimentoCella + "\" t=\"inlineStr\"");
			writerOut.write(" s=\"" + indiceStile + "\">");
			writerOut.write("<is><t>" + valore + "</t></is>");
			writerOut.write("</c>"); 
	}
	

	protected void creazioneCellaNumerica(Writer writerOut, int indiceRiga, int indiceCella, long valore, int indiceStile) throws Exception { 
			String riferimentoCella = new CellReference(indiceRiga, indiceCella).formatAsString();
			writerOut.write("<c r=\"" + riferimentoCella + "\" t=\"n\"");
			writerOut.write(" s=\"" + indiceStile + "\">");
			writerOut.write("<v>" + valore + "</v>");
			writerOut.write("</c>"); 
	}
	

	protected void creazioneCellaNumerica(Writer writerOut, int indiceRiga, int indiceCella, double valore, int indiceStile) throws Exception { 
			String riferimentoCella = new CellReference(indiceRiga, indiceCella).formatAsString();
			writerOut.write("<c r=\"" + riferimentoCella + "\" t=\"n\"");
			writerOut.write(" s=\"" + indiceStile + "\">");
			writerOut.write("<v>" + valore + "</v>");
			writerOut.write("</c>"); 
	}
	
	protected void creazioneCellaNumerica(Writer writerOut, int indiceRiga, int indiceCella, String valore, int indiceStile) throws Exception { 
		creazioneCellaNumerica(writerOut, indiceRiga, indiceCella, Long.parseLong( valore ), indiceStile);
	}
	
	protected void creazioneRiga(Writer writerOut, int indiceRiga) throws Exception { 
			writerOut.write("<row r=\"" + (indiceRiga + 1) + "\">\n"); 
	}
	

	protected void chiusuraRiga(Writer writerOut) throws Exception { 
			writerOut.write("</row>\n");
	}
	
	

	/*******************************************************************************************************************************************************************************************************************************************************************************************************
	 * Metodo incaricato di "fillare" il file di destinazione.
	 * 
	 * @param template
	 * @param sheets
	 * @param outputStream
	 * @throws Exception
	 */
	private void fillFile(File template, Map<String, File> sheets, OutputStream outputStream) throws Exception { 
			ZipFile zipFile = new ZipFile(template);

			ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream);
			@SuppressWarnings("unchecked")
			Enumeration<ZipEntry> componenti = (Enumeration<ZipEntry>) zipFile.entries();
			/*
			 * Vengono inserite nel file di destinazione TUTTE le componenti del file di "template".
			 */
			while (componenti.hasMoreElements()) {
				ZipEntry zipEntry = componenti.nextElement();

				if (!sheets.containsKey(zipEntry.getName())) {
					zipOutputStream.putNextEntry(new ZipEntry(zipEntry.getName()));
					InputStream inputStream = zipFile.getInputStream(zipEntry);
					this.copiaStream(inputStream, zipOutputStream);
					inputStream.close();
				}
				/*
				 * Vengono inseriti gli sheet nel file di destinazione.
				 */
				else if (sheets.containsKey(zipEntry.getName())) {
					zipOutputStream.putNextEntry(new ZipEntry(zipEntry.getName()));
					InputStream inputStream = new FileInputStream(sheets.get(zipEntry.getName()));
					this.copiaStream(inputStream, zipOutputStream);
					inputStream.close(); 
				}
			}
			zipOutputStream.flush();
			zipOutputStream.close();
			zipFile.close(); 
	}
	
	
	
	private void copiaStream(InputStream in, OutputStream out) throws Exception { 
			byte[] contenuto = new byte[1024];
			int caratteri = in.read(contenuto);
			while (caratteri >= 0) {
				out.write(contenuto, 0, caratteri);
				caratteri = in.read(contenuto);
			} 
	}
	
	protected abstract Map<String, XSSFCellStyle> creazioneStyles(Workbook workbook) throws Exception;
//	{
//		 
//		Map<String, XSSFCellStyle> stili = new HashMap<String, XSSFCellStyle>();
//		/*
//		 * FONTS
//		 */
//		Font fontGrassetto10Bianco = this.creazioneFont(workbook, (short) 10, "Arial", HSSFColor.WHITE.index, false, true);
//		Font fontGrassetto10Nero = this.creazioneFont(workbook, (short) 10, "Arial", HSSFColor.BLACK.index, false, true);
//		Font font10 = this.creazioneFont(workbook, (short) 10, "Arial", HSSFColor.BLACK.index, false, false);
//		/*
//		 * STILI
//		 */
//		// Colori Java.
//		java.awt.Color coloreTitolo = new java.awt.Color(79, 129, 189);
//		java.awt.Color coloreRigheDispari = new java.awt.Color(219, 229, 241);
//		java.awt.Color coloreRighePari = new java.awt.Color(255, 255, 255);
//		// Colori Poi.
//		XSSFColor titolo = new XSSFColor(coloreTitolo);
//		XSSFColor righePari = new XSSFColor(coloreRighePari);
//		XSSFColor righeDispari = new XSSFColor(coloreRigheDispari);
//		// Stili.
//		XSSFCellStyle arialDieciGrassettoCentroBianco = this.creazioneStyle(workbook, fontGrassetto10Bianco, XSSFCellStyle.ALIGN_CENTER, CellStyle.BORDER_THIN, CellStyle.BORDER_THIN, CellStyle.BORDER_THIN, CellStyle.BORDER_THIN, titolo, true);
//		XSSFCellStyle arialDieciGrassettoCentroNero = this.creazioneStyle(workbook, fontGrassetto10Nero, XSSFCellStyle.ALIGN_CENTER, CellStyle.BORDER_THIN, CellStyle.BORDER_THIN, CellStyle.BORDER_THIN, CellStyle.BORDER_THIN, titolo, true);
//		XSSFCellStyle arialDieciGrassettoDestraNero = this.creazioneStyle(workbook, fontGrassetto10Nero, XSSFCellStyle.ALIGN_RIGHT, CellStyle.BORDER_THIN, CellStyle.BORDER_THIN, CellStyle.BORDER_THIN, CellStyle.BORDER_THIN, righeDispari, false);
//		XSSFCellStyle arialDieciGrassettoCentroNero2 = this.creazioneStyle(workbook, fontGrassetto10Nero, XSSFCellStyle.ALIGN_CENTER, CellStyle.BORDER_THIN, CellStyle.BORDER_THIN, CellStyle.BORDER_THIN, CellStyle.BORDER_THIN, righeDispari, true);
//		XSSFCellStyle arialDieciGrassettoSinistraNero = this.creazioneStyle(workbook, fontGrassetto10Nero, XSSFCellStyle.ALIGN_LEFT, CellStyle.BORDER_THIN, CellStyle.BORDER_THIN, CellStyle.BORDER_THIN, CellStyle.BORDER_THIN, righeDispari, false);
//		XSSFCellStyle arialDieciDestraSfondoBlu = this.creazioneStyle(workbook, font10, XSSFCellStyle.ALIGN_RIGHT, CellStyle.BORDER_THIN, CellStyle.BORDER_THIN, CellStyle.BORDER_THIN, CellStyle.BORDER_THIN, righeDispari, false);
//		XSSFCellStyle arialDieciSinistraSfondoBlu = this.creazioneStyle(workbook, font10, XSSFCellStyle.ALIGN_LEFT, CellStyle.BORDER_THIN, CellStyle.BORDER_THIN, CellStyle.BORDER_THIN, CellStyle.BORDER_THIN, righeDispari, false);
//		XSSFCellStyle arialDieciDestraSfondoBianco = this.creazioneStyle(workbook, font10, XSSFCellStyle.ALIGN_RIGHT, CellStyle.BORDER_THIN, CellStyle.BORDER_THIN, CellStyle.BORDER_THIN, CellStyle.BORDER_THIN, righePari, false);
//		XSSFCellStyle arialDieciSinistraSfondoBianco = this.creazioneStyle(workbook, font10, XSSFCellStyle.ALIGN_LEFT, CellStyle.BORDER_THIN, CellStyle.BORDER_THIN, CellStyle.BORDER_THIN, CellStyle.BORDER_THIN, righePari, false);
//
//		stili.put(ARIAL_DIECI_GRASSETTO_CENTRO_BIANCO, arialDieciGrassettoCentroBianco);
//		stili.put(ARIAL_DIECI_GRASSETTO_CENTRO_NERO, arialDieciGrassettoCentroNero);
//		stili.put(ARIAL_DIECI_GRASSETTO_DESTRA_NERO, arialDieciGrassettoDestraNero);
//		stili.put(ARIAL_DIECI_GRASSETTO_CENTRO_NERO2, arialDieciGrassettoCentroNero2);
//		stili.put(ARIAL_DIECI_GRASSETTO_SINISTRA_NERO, arialDieciGrassettoSinistraNero);
//		stili.put(ARIAL_DIECI_DESTRA_SF_BLU, arialDieciDestraSfondoBlu);
//		stili.put(ARIAL_DIECI_SINISTRA_SF_BLU, arialDieciSinistraSfondoBlu);
//		stili.put(ARIAL_DIECI_DESTRA_SF_BIANCO, arialDieciDestraSfondoBianco);
//		stili.put(ARIAL_DIECI_SINISTRA_SF_BIANCO, arialDieciSinistraSfondoBianco);
//
//		return stili; 
//	}
	
	
	protected Font creazioneFont(Workbook workbook, short fontHeigh, String fontName, short fontColor, boolean italic, boolean bold) throws Exception {
		 
			Font font = workbook.createFont();
			font.setColor(fontColor);
			font.setFontHeightInPoints(fontHeigh);
			font.setFontName(fontName);
			if (bold) {
				font.setBoldweight(Font.BOLDWEIGHT_BOLD);
			}
			font.setItalic(italic);
			return font;
		 
	}
	
	
	protected XSSFCellStyle creazioneStyle(Workbook workbook, Font font, short alignment, short bordoSup, short bordoDestro, short bordoInf, short bordoSin, XSSFColor foregroundColor, boolean aCapoAutomatico, boolean moneyFormat) throws Exception {
	 
			XSSFCellStyle style = (XSSFCellStyle) workbook.createCellStyle();
			style.setFont(font);
			// Bordo cella.
			style.setAlignment(alignment);
			style.setBorderTop(bordoSup);
			style.setBorderRight(bordoDestro);
			style.setBorderBottom(bordoInf);
			style.setBorderLeft(bordoSin);
			// Colorazione sfondo cella.
			style.setFillForegroundColor(foregroundColor);
			style.setFillPattern(CellStyle.SOLID_FOREGROUND);
			// A capo automatico.
			style.setWrapText(aCapoAutomatico);
			// Colorazione bordo cella.
			// Colore Java.
			java.awt.Color coloreBordo = new java.awt.Color(158, 182, 206);
			// Colore Poi.
			XSSFColor bordo = new XSSFColor(coloreBordo);
			style.setTopBorderColor(bordo);
			style.setRightBorderColor(bordo);
			style.setBottomBorderColor(bordo);
			style.setLeftBorderColor(bordo);
			// Allineamento contenuto cella.
			style.setVerticalAlignment(XSSFCellStyle.VERTICAL_TOP); 
			
			if (moneyFormat) { 
				style.setDataFormat(workbook.createDataFormat().getFormat("#,##0.00")); 
			}
			
			return style; 
	}
}
